package script;

import java.util.ArrayList;

import main.ErrorException;
import define.Common;
import define.Config;
import define.ErrorDefine;
import define.Keyword;
import define.VariableType;

public class Variable implements BaseExpress
{
	private StringBuffer m_stringValue;
	private String m_name;
	private int m_intValue;
	private int m_start;
	private int m_listIndex;
	private String m_mapKey;
	private ArrayList<StringBuffer> m_valueList;
	private ArrayList<String> m_keyList;
	private VariableType m_type;
	
	public Variable(Script script, int start, int end) throws ErrorException
	{
		if(start > end)
		{
			throw new ErrorException(ErrorDefine.E_NULL_VARIABLE_ERROR, start);
		}
		m_start = start;
		m_listIndex = -1;
		if(script.m_scriptCode[start] == Keyword.E_VARIABLE_KEY.getCode() 
				&& script.m_scriptCode[end] == Keyword.E_VARIABLE_KEY.getCode())
		{
			int index = Common.find(Keyword.E_CELL_SPLIT_KEY.getChar(), script.m_scriptCode, start + 1, end - 1);
			if(index == Config.NO_FIND || script.m_scriptCode[index - 1] == Keyword.E_ESC_KEY.getCode())
			{
				m_name = Common.buildString(script.m_scriptCode, start + 1, end - 1);
				m_type = VariableType.E_VARIABLE_VT;
			}
			else if(index == start + 1 || index == end - 1)
			{
				throw new ErrorException(ErrorDefine.E_BUILD_STRING_ERROR, start);
			}
			else
			{
				m_name = Common.buildString(script.m_scriptCode, start + 1, index - 1);
				if(script.m_scriptCode[index + 1] == Keyword.E_CELL_STRING_KEY.getChar())
				{
					m_mapKey = Common.buildString(script.m_scriptCode, index + 2, end - 1);
					m_type = VariableType.E_MAP_ELEMENT_VT;
				}
				else
				{
					String value = Common.buildString(script.m_scriptCode, index + 1, end - 1);
					Integer i = Common.isInt(value);
					if(i == null)
					{
						throw new ErrorException(ErrorDefine.E_LIST_INDEX_MUST_NUMBER_ERROR, value, start);
					}
					m_listIndex = i;
					m_type = VariableType.E_LIST_ELEMENT_VT;
				}
			}
			m_stringValue = null;
		}
		else
		{
			m_name = null;
			m_stringValue = new StringBuffer(Common.buildString(script.m_scriptCode, start, end));
			m_type = VariableType.E_STRING_VT;
		}
	}
	
	public Variable(String value, int start)
	{
		m_name = null;
		m_stringValue = new StringBuffer(value);
		m_start = start;
		m_listIndex = -1;
		m_type = VariableType.E_STRING_VT;
	}
	
	public void changeToList()
	{
		m_valueList = new ArrayList<>();
		m_type = VariableType.E_LIST_VT;
	}
	
	public void changeToMap()
	{
		m_valueList = new ArrayList<StringBuffer>();
		m_keyList = new ArrayList<String>();
		m_type = VariableType.E_MAP_VT;
	}
	
	public void cancelListMapToVariable()
	{
		m_valueList = null;
		m_keyList = null;
		m_mapKey = null;
		m_type = VariableType.E_VARIABLE_VT;
	}
	
	public ArrayList<StringBuffer> getValueList()
	{
		return m_valueList;
	}
	
	public StringBuffer getValueByKey(String str)
	{
		for(int i = 0, max = m_keyList.size(); i < max; ++i)
		{
			if(str.compareTo(m_keyList.get(i)) == 0)
			{
				return m_valueList.get(i);
			}
		}
		return new StringBuffer("");
	}
	
	public String getMapKey()
	{
		return m_mapKey;
	}
	
	public int getListIndex()
	{
		return m_listIndex;
	}
	
	public int getStart()
	{
		return m_start;
	}
	
	public String getName()
	{
		if(m_name == null)
		{
			return "";
		}
		return m_name;
	}
	
	public void addKeyValue(String key, StringBuffer value)
	{
		for(int i = 0, max = m_keyList.size(); i < max; ++i)
		{
			if(key.compareTo(m_keyList.get(i)) == 0)
			{
				m_keyList.set(i, key);
				m_valueList.set(i, value);
				return;
			}
		}
		m_keyList.add(key);
		m_valueList.add(value);
	}
	
	public StringBuffer getValue() throws ErrorException
	{
		return m_stringValue;
	}
	
	public int getIntValue()
	{
		assert m_name != null: "it's a string varivale";
		return m_intValue;
	}
	
	public void setIntValue(int value)
	{
		assert m_name != null: "it's a string varivale";
		m_intValue = value;
	}
	
	public void setStringValue()
	{
		assert m_name != null: "it's a string varivale";
		m_stringValue = new StringBuffer("" + m_intValue);
	}
	
	public void setStringValue(StringBuffer value)
	{
		assert m_name != null: "it's a string varivale";
		m_stringValue = value;
	}

	public VariableType getType()
	{
		return m_type;
	}
	
	public void removeByIndex(ArrayList<Integer> list, int position) throws ErrorException
	{
		int size = list.size();
		for(int i = 0; i < size; ++i)
		{
			for(int j = i + 1; j < size; ++j)
			{
				if(list.get(i) < list.get(j))
				{
					int temp = list.get(i);
					list.set(i, list.get(j));
					list.set(j, temp);
				}
			}
		}
		for(int i = 0; i < size; ++i)
		{
			int index = list.get(i);
			if(index < 0 || index >= m_valueList.size())
			{
				throw new ErrorException(ErrorDefine.E_OUT_RANGE_ERROR, index + "", position);
			}
			m_valueList.remove(index);
		}
	}
	
	public void removeByKey(String key)
	{
		for(int i = 0, size = m_keyList.size(); i < size; ++i)
		{
			if(key.compareTo(m_keyList.get(i)) == 0)
			{
				m_keyList.remove(i);
				m_valueList.remove(i);
				return;
			}
		}
	}
	
	public void removeByValue(StringBuffer value)
	{
		String str = value.toString();
		for(int i = 0, size = m_valueList.size(); i < size; ++i)
		{
			if(str.compareTo(m_valueList.get(i).toString()) == 0)
			{
				if(m_type == VariableType.E_MAP_VT)
				{
					m_keyList.remove(i);
				}
				m_valueList.remove(i);
				return;
			}
		}
	}
}
